package com.lagou.rpc.consumer.proxy;

import com.alibaba.fastjson.JSON;
import com.lagou.rpc.common.RpcRequest;
import com.lagou.rpc.common.RpcResponse;
import com.lagou.rpc.consumer.client.RpcClient;
import com.lagou.rpc.consumer.client.RpcConsumer;
import com.lagou.rpc.consumer.loadbalance.LoadBalanceStrategy;
import com.lagou.rpc.consumer.loadbalance.impl.MinCostLoadBalance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.UUID;

/**
 * 客户端代理类-创建代理对象
 * 1.封装request请求对象
 * 2.创建RpcClient对象
 * 3.发送消息
 * 4.返回结果
 */
@Service
public class RpcClientProxy {

    @Autowired
    private RpcConsumer rpcConsumer;

    LoadBalanceStrategy load = new MinCostLoadBalance();

    public  Object createProxy(Class serviceClass) {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                new Class[]{serviceClass}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //1.封装request请求对象
                RpcRequest rpcRequest = new RpcRequest();
                rpcRequest.setRequestId(UUID.randomUUID().toString());
                String serviceName = method.getDeclaringClass().getName();
                rpcRequest.setClassName(serviceName);
                rpcRequest.setMethodName(method.getName());
                rpcRequest.setParameterTypes(method.getParameterTypes());
                rpcRequest.setParameters(args);
                //2.获取负载均衡策略获取连接地址
                Map<String, String> rpcClientPool = rpcConsumer.getRpcClientPool();
                if (rpcClientPool == null || rpcClientPool.isEmpty()) {
                    throw new RuntimeException("没有可连接的rpc客户端！");
                }
                String connectString = load.route(rpcClientPool, serviceName);
                if (connectString == null) {
                    throw new RuntimeException("没有获取导致可连接的rpc客户端！");
                }
                //创建RpcClient对象
                String[] split = connectString.split(":");
                RpcClient rpcClient = new RpcClient(split[0], Integer.parseInt(split[1]));
                try {
                    //3.发送消息
                    Object responseMsg = rpcClient.send(JSON.toJSONString(rpcRequest));
                    RpcResponse rpcResponse = JSON.parseObject(responseMsg.toString(), RpcResponse.class);
                    if (rpcResponse.getError() != null) {
                        throw new RuntimeException(rpcResponse.getError());
                    }
                    //4.返回结果
                    Object result = rpcResponse.getResult();
                    return JSON.parseObject(result.toString(), method.getReturnType());
                } catch (Exception e) {
                    throw e;
                } finally {
                    rpcClient.close();
                }
            }
        });
    }

}
